package managers;

import java.util.ArrayList;

import ontology.PartOfSpeech;
import rules.Rule;

import components.Component;
import components.InputXMLDocument;
import components.Leaf;
import components.Phrase;

import features.Feature;

public class TextGenerator {
	
	private static TextGenerator instance;
	
	public static TextGenerator getInstance(){
		if(instance == null)
			instance = new TextGenerator();
		return instance;
	}
	
	//Generation Engine
	//creates a copy and applies the rules to that copy
	public InputXMLDocument applyRules(InputXMLDocument document){
		InputXMLDocument copy = document.getCopy(true);
		ArrayList<Component> clauses = copy.getClauses();
		
		ArrayList<Rule> rules = RuleManager.getInstance().getRulesInOrder();
		for(Component clause: clauses)
			for(Rule rule: rules)
				//if(rule.isOn())
					rule.applyIfMatch(clause);
		
		return copy;
	}
	
	//Helper Methods
	public Component getComponentByTag(ArrayList<Component> components, int desiredTag){
		for(Component c: components)
			if(c.getTag() == desiredTag)
				return c;
		return null;
	}
	
	//TEST METHODS
	
	public void testMatching(){
		testMatch1();
		testMatch2();
		testMatch3();
		testMatch4();
	}
	
	private static void testMatch1(){
		//Pattern
		Phrase clausePat = (Phrase) Component.createInstance(PartOfSpeech.CLAUSE, false);
		Phrase npPat = (Phrase) Component.createInstance(PartOfSpeech.NOUN_PHRASE, false);
		clausePat.addChild(npPat);
		npPat.setFeature(new Feature("Semantic Role", "Agent", true));
		
		clausePat.setTag(1);
		
		//Input
		Phrase clause = (Phrase) Component.createInstance(PartOfSpeech.CLAUSE, true);
		Phrase np = (Phrase)Component.createInstance(PartOfSpeech.NOUN_PHRASE, true);
		Leaf n = (Leaf) Component.createInstance(PartOfSpeech.NOUN, true);
		Phrase vp = (Phrase)Component.createInstance(PartOfSpeech.VERB_PHRASE, true);
		Leaf v = (Leaf)Component.createInstance(PartOfSpeech.VERB,true);
		
		clause.addChild(np);
		clause.addChild(vp);
		np.addChild(n);
		vp.addChild(v);
		
		//Set features
		np.setFeature(new Feature("Semantic Role", "Agent", true));
		n.setConcept("HUMAN");
		n.setLexicalSense("A");
		v.setConcept("SLEEP");
		v.setLexicalSense("A");
		v.setFeature(new Feature("Time", "Present", true));
		
		System.out.println("TEST MATCH 1:");
		printTestResults(clause, clausePat);
	}
	
	private static void testMatch2(){
		//Pattern
		Phrase clausePat = (Phrase) Component.createInstance(PartOfSpeech.CLAUSE, false);
		Phrase npPat = (Phrase) Component.createInstance(PartOfSpeech.NOUN_PHRASE, false);
		clausePat.addChild(npPat);
		npPat.setFeature(new Feature("Semantic Role", "Agent", true));
		
		clausePat.setTag(1);
		
		//Input
		Phrase clause = (Phrase) Component.createInstance(PartOfSpeech.CLAUSE, true);
		Phrase np = (Phrase)Component.createInstance(PartOfSpeech.NOUN_PHRASE, true);
		Leaf n = (Leaf) Component.createInstance(PartOfSpeech.NOUN, true);
		Phrase vp = (Phrase)Component.createInstance(PartOfSpeech.VERB_PHRASE, true);
		Leaf v = (Leaf)Component.createInstance(PartOfSpeech.VERB,true);
		
		clause.addChild(vp);
		clause.addChild(np);
		np.addChild(n);
		vp.addChild(v);
		
		//Set features
		np.setFeature(new Feature("Semantic Role", "Agent", true));
		n.setConcept("HUMAN");
		n.setLexicalSense("A");
		v.setConcept("SLEEP");
		v.setLexicalSense("A");
		v.setFeature(new Feature("Time", "Present", true));
		
		System.out.println("TEST MATCH 2:");
		printTestResults(clause, clausePat);
	}
	
	private static void testMatch3(){
		//Pattern
		Phrase clausePat = (Phrase) Component.createInstance(PartOfSpeech.CLAUSE, false);
		Phrase npPat = (Phrase) Component.createInstance(PartOfSpeech.NOUN_PHRASE, false);
		clausePat.addChild(npPat);
		npPat.setFeature(new Feature("Semantic Role", "Patient", true));
		
		clausePat.setTag(1);
		
		//Input
		Phrase clause = (Phrase) Component.createInstance(PartOfSpeech.CLAUSE, true);
		Phrase np = (Phrase)Component.createInstance(PartOfSpeech.NOUN_PHRASE, true);
		Leaf n = (Leaf) Component.createInstance(PartOfSpeech.NOUN, true);
		Phrase vp = (Phrase)Component.createInstance(PartOfSpeech.VERB_PHRASE, true);
		Leaf v = (Leaf)Component.createInstance(PartOfSpeech.VERB,true);
		
		clause.addChild(np);
		clause.addChild(vp);
		np.addChild(n);
		vp.addChild(v);
		
		//Set features
		np.setFeature(new Feature("Semantic Role", "Agent", true));
		n.setConcept("HUMAN");
		n.setLexicalSense("A");
		v.setConcept("SLEEP");
		v.setLexicalSense("A");
		v.setFeature(new Feature("Time", "Present", true));
		
		System.out.println("TEST MATCH 3:");
		printTestResults(clause, clausePat);
	}

	private static void testMatch4(){
		//Pattern
		Phrase clausePat = (Phrase) Component.createInstance(PartOfSpeech.CLAUSE, false);
		Phrase npPat1 = (Phrase) Component.createInstance(PartOfSpeech.NOUN_PHRASE, false);
		Leaf nPat1 = (Leaf)Component.createInstance(PartOfSpeech.NOUN, false);
		Phrase npPat2 = (Phrase) Component.createInstance(PartOfSpeech.NOUN_PHRASE, false);
		Leaf nPat2 = (Leaf)Component.createInstance(PartOfSpeech.NOUN, false);
		
		clausePat.addChild(npPat1);
		clausePat.addChild(npPat2);
		npPat1.addChild(nPat1);
		npPat2.addChild(nPat2);
		
		npPat1.setFeature(new Feature("Semantic Role", "Agent", true));
		nPat1.setFeature(new Feature("Number", "Plural", true));
		npPat2.setFeature(new Feature("Semantic Role", "Patient", true));
		nPat2.setFeature(new Feature("Number", "Plural", true));
		
		clausePat.setTag(1);
		
		//Input
		Phrase clause =  (Phrase) Component.createInstance(PartOfSpeech.CLAUSE, true);
		Phrase np1 = (Phrase) Component.createInstance(PartOfSpeech.NOUN_PHRASE, true);
		Leaf n1 = (Leaf)Component.createInstance(PartOfSpeech.NOUN, true);
		Phrase vp1 = (Phrase) Component.createInstance(PartOfSpeech.VERB_PHRASE, true);
		Leaf v1 = (Leaf)Component.createInstance(PartOfSpeech.VERB, true);
		Phrase np2 = (Phrase) Component.createInstance(PartOfSpeech.NOUN_PHRASE, true);
		Leaf n2 = (Leaf)Component.createInstance(PartOfSpeech.NOUN, true);
		
		clause.addChild(np1);
		clause.addChild(vp1);
		clause.addChild(np2);
		
		np1.addChild(n1);
		vp1.addChild(v1);
		np2.addChild(n2);
		
		np1.setFeature(new Feature("Semantic Role", "Patient", true));
		n1.setFeature(new Feature("Number", "Plural", true));
		v1.setFeature(new Feature("Time", "Present", true));
		np2.setFeature(new Feature("Semantic Role", "Agent", true));
		n2.setFeature(new Feature("Number", "Plural", true));
		
		n1.setConcept("BUILDING");
		n1.setLexicalSense("A");
		n2.setConcept("HUMAN");
		n2.setLexicalSense("A");
		
		
		System.out.println("TEST MATCH 4:");
		printTestResults(clause, clausePat);
	}
	
	private static void printTestResults(Component input, Component pattern){
		
		if(input.matches(pattern)){
			System.out.println("true");
			ArrayList<Component> matched = input.getMatchedComponents(pattern);
			for(Component m: matched)
				System.out.println(m.getTag()+" "+m);
			
		}
		else
			System.out.println("false");
		
		System.out.println();
	}
	
}
